package com.hhkj.api.student.service.extend.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hhkj.admin.student.domain.Student;
import com.hhkj.admin.student.domain.StudentCourse;
import com.hhkj.admin.student.model.dopo.StudentPo;
import com.hhkj.admin.student.model.req.StudentCourseReq;
import com.hhkj.admin.student.service.base.StudentCourseService;
import com.hhkj.admin.student.service.base.StudentService;
import com.hhkj.api.student.service.extend.ApiStudentExtendService;
import com.hhkj.admin.student.common.cont.StudentConst;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.exception.student.WxLoginException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * 学员Service接口
 *
 * @author ruoyi
 * @since 2023-06-08
 */
@Slf4j
@Service
public class ApiStudentExtendServiceImpl implements ApiStudentExtendService {
    @Autowired
    private StudentService studentService;
    @Autowired
    private StudentCourseService studentCourseService;
    // 小程序 appId
    @Value("${wx.appid}")
    private String appid;
    // 小程序 appSecret
    @Value("${wx.secret}")
    private String secret;

    @Value("${spring.profiles.active}")
    private String active;

    /**
     * 校验基础信息（账号密码、科目、状态）
     *
     * @param studentReq 参数
     * @param flag       true检验科目 false不校验科目
     * @return 正确查询出来的学员信息
     */
    @Override
    public Student verifyCommonInfo(Student studentReq, boolean flag) {

        if (StringUtils.isEmpty(studentReq.getIdCard())
                || StringUtils.isEmpty(studentReq.getPassword())) {
            log.info("账号密码不能为空！,code不能为空！");
            throw new GlobalException("账号密码错误！");
        }
        if (flag) {
            if (studentReq.getCourseId() == null
                /* || studentReq.getCode() == null*/) {
                log.info("科目不能为空！,code不能为空！");
                throw new GlobalException("科目不能为空！");
            }
        }

        List<StudentPo> students = studentService.selectStudentCourseByDo(studentReq);
        if (students.size() == 0) {
            log.info("账号密码错误，或者未审核通过，或者未设置账号期限");
            throw new GlobalException("账号或者密码错误！");
        }
        Student student = students.get(0);
        if (!"dev".equals(active)) {
            boolean b = SecurityUtils.matchesPassword(studentReq.getPassword(), student.getPassword());
            if (!b) {
                log.info("账号或者密码错误！");
                throw new GlobalException("账号或者密码错误！");
            }
        }
        if (!StudentConst.AuditCode.STATUS_PASS.getCode().equals(student.getStatus())) {
            log.info("未审核通过，不允许登录！");
            throw new GlobalException("账号或者密码错误！");
        }
        student.setCode(studentReq.getCode());
        student.setBingFlag(studentReq.getBingFlag());
        student.setOpenIdFlag(studentReq.getOpenIdFlag());
        return student;
    }

    /**
     * 校验学员题库类型、是否到期、是否同一个微信登录
     *
     * @param studentReq 传参
     */
    @Override
    public void verifyInfo(Student studentReq) {
        //校验学员是否指定题库类型
        if (studentReq.getCourseBankTypeId() == null) {
            log.info("该账号未指定题库类型");
            throw new GlobalException("账号或者密码错误！");
        }
        //校验学员是否指定到期日期
        if (studentReq.getLineDate() == null) {
            log.info("该账号未指定到期日期");
            throw new GlobalException("账号或者密码错误！");
        }
        //校验学员是否到期
        StudentCourse one = studentCourseService.getOne(Wrappers.<StudentCourse>lambdaQuery()
                .eq(StudentCourse::getStudentId, studentReq.getId())
                .eq(StudentCourse::getCourseId, studentReq.getCourseId())
                .eq(StudentCourse::getStatus, StudentConst.AuditCode.STATUS_PASS.getCode()));
        if (ObjectUtil.isNotNull(one.getStartDate()) && one.getStartDate().after(new Date())) {
            log.info("该账号未到有效期");
            throw new GlobalException("账号或者密码错误！");
        }
        if (StudentConst.AuditCode.STATUS_OUT_TIME.getCode().equals(one.getStatus())) {
            log.info("该账号已过期");
            throw new GlobalException("账号或者密码错误！");
        }
        //校验微信登录内容
        // if (!StudentConst.OpenIdCode.NO_VERIFY.getCode().equals(studentReq.getOpenIdFlag())) {
        //     verifyWxInfo(studentReq, one);
        // }
    }

    /**
     * 进行微信信息的校验
     *
     * @param studentReq    参数
     * @param studentCourse 学员登录科目
     */
    private void verifyWxInfo(Student studentReq, StudentCourse studentCourse) {
        //获取openId
        String openId = getOpenId(studentReq);
        //校验
        if (StudentConst.BingTypeCode.BIND.getCode().equals(studentReq.getBingFlag())) {
            //尝试进行绑定
            if (ObjectUtil.isNotNull(studentCourse.getOpenId())) {
                //如果已经绑定过，就提示已绑定请勿重新绑定
                throw new GlobalException("已绑定微信，请勿重复绑定！");
            }
            //检查该openId是否已绑定其他用户student，有就提示该微信已绑定其他账户
            long count = studentCourseService.count(Wrappers.<StudentCourse>lambdaQuery()
                    .eq(StudentCourse::getOpenId, openId)
                    .ne(StudentCourse::getStudentId, studentCourse.getStudentId()));
            if (count > 0) {
                throw new GlobalException("该微信已绑定其他账户！");
            }
            //如果未绑定过，就进行绑定
            StudentCourseReq studentCourseReq = new StudentCourseReq();
            studentCourseReq.setOpenId(openId);
            studentCourseService.updateStudentCourseByIdList(CollectionUtil.newArrayList(studentCourse.getId()), studentCourseReq);
        } else {
            //0本次不绑定，正常登录
            if (ObjectUtil.isNotNull(studentCourse.getOpenId())) {
                //已绑定就校验是否一致
                if (!studentCourse.getOpenId().equals(openId)) {
                    log.info("OpenId不一致！该账号已绑定其他微信！");
                    throw new GlobalException("该账号已绑定其他微信！");
                }
            } else {
                //需要检查是否已经绑定，未绑定提示去绑定
                throw new WxLoginException(5001L, "请先绑定微信！");
            }
        }
    }

    /**
     * 获取openId
     *
     * @param studentReq jsCode
     * @return openId
     */
    private String getOpenId(Student studentReq) {
        //非第三方授权账号获取小程序service
        WxMaService wxMaService = new WxMaServiceImpl();
        WxMaDefaultConfigImpl wxConfig = new WxMaDefaultConfigImpl();
        //小程序 appId
        wxConfig.setAppid(appid);
        //小程序 appSecret
        wxConfig.setSecret(secret);
        wxMaService.setWxMaConfig(wxConfig);
        try {
            WxMaJscode2SessionResult jscode2session = wxMaService.jsCode2SessionInfo(studentReq.getCode());
            return jscode2session.getOpenid();
        } catch (WxErrorException e) {
            e.printStackTrace();
            throw new RuntimeException("小程序登录微信失败!");
        }
    }
}
